{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# `std::thread` 的生命周期与可移动性\n",
    "\n",
    "- **生命周期**：创建线程对象时即启动新线程。必须在 `std::thread` 析构前调用 `join()` 或 `detach()`：\n",
    "  - `join()` 阻塞直到线程结束，线程对象进入 “not joinable” 状态。\n",
    "  - `detach()` 让线程后台运行，终止时资源自动回收，但无法再同步它。\n",
    "- 若线程对象析构时仍处于 joinable 状态 -> 调用 `std::terminate()`。\n",
    "- **可移动性**：`std::thread` 可移动但不可拷贝。移动转移线程所有权（joinable 状态也随之转移）。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "> AI:\n",
    "\n",
    "在 C++ 标准里，`std::thread` 的析构函数有一个硬性要求：析构时，线程对象必须已经不再是 *joinable* 的，也就是你要么已经调用过 `join()`，要么调用了 `detach()`。否则，如果线程对象在析构时仍然是 joinable 状态，析构函数就会直接调用 `std::terminate()`，导致程序立即终止。\n",
    "\n",
    "这么设计是为了避免资源泄漏或不确定行为：如果一个线程还在运行，你却让对应的 `std::thread` 对象消失，系统不知道该如何安全地处理那个运行中的线程，因此直接终止程序以提醒你必须显式管理线程的生命周期。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "vscode": {
     "languageId": "cpp"
    }
   },
   "outputs": [],
   "source": [
    "#include <iostream>\n",
    "#include <thread>\n",
    "\n",
    "int main() {\n",
    "    std::thread t([] {\n",
    "        std::cout << \"worker\\n\";\n",
    "    });\n",
    "\n",
    "    std::thread t2 = std::move(t); // t 不再 joinable，t2 接管\n",
    "    if (t2.joinable()) t2.join();\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# `std::async` 启动策略\n",
    "\n",
    "- 默认策略：`std::launch::async | std::launch::deferred`（实现可选择立即异步执行或延迟到 `get()` 调用时执行）。\n",
    "- 强制异步执行：显式传入 `std::launch::async`。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "vscode": {
     "languageId": "cpp"
    }
   },
   "outputs": [],
   "source": [
    "#include <future>\n",
    "#include <iostream>\n",
    "\n",
    "int main() {\n",
    "    auto fut = std::async(std::launch::async, [] {\n",
    "        return 42;\n",
    "    });\n",
    "    std::cout << fut.get() << '\\n';\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# `std::mutex`、`std::shared_mutex`、`std::recursive_mutex` 场景\n",
    "\n",
    "| 类型                   | 场景                                                      |\n",
    "| ---------------------- | --------------------------------------------------------- |\n",
    "| `std::mutex`           | 互斥访问，最常用，单一写/读锁                             |\n",
    "| `std::shared_mutex`    | 多读单写：`lock_shared()` 允许多个读者，`lock()` 独占写者 |\n",
    "| `std::recursive_mutex` | 同一线程可重入锁多次（谨慎使用，可能掩盖设计问题）        |"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## `std::shared_mutex` 的读写锁模式\n",
    "\n",
    "`std::shared_mutex` 提供两类锁：\n",
    "\n",
    "- `lock()` / `unlock()`：独占锁（写者）。\n",
    "- `lock_shared()` / `unlock_shared()`：共享锁（读者）。\n",
    "\n",
    "使用建议：\n",
    "\n",
    "- 读多写少场景（如缓存、配置读取）可显著提升吞吐。\n",
    "- 需要避免写者饥饿：某些实现为公平锁，若非公平可辅助条件变量/升级锁策略。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "vscode": {
     "languageId": "cpp"
    }
   },
   "outputs": [],
   "source": [
    "#include <shared_mutex>\n",
    "#include <string>\n",
    "#include <unordered_map>\n",
    "#include <optional>\n",
    "\n",
    "class ThreadSafeCache {\n",
    "public:\n",
    "    void set(std::string key, int value) {\n",
    "        std::unique_lock lock(mutex_); // 写锁\n",
    "        data_[std::move(key)] = value;\n",
    "    }\n",
    "\n",
    "    std::optional<int> get(const std::string& key) const {\n",
    "        std::shared_lock lock(mutex_); // 读锁\n",
    "        if (auto it = data_.find(key); it != data_.end())\n",
    "            return it->second;\n",
    "        return std::nullopt;\n",
    "    }\n",
    "\n",
    "private:\n",
    "    mutable std::shared_mutex mutex_;\n",
    "    std::unordered_map<std::string, int> data_;\n",
    "};"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "##  `std::shared_mutex` 进阶技巧\n",
    "\n",
    "- **升级锁**：C++17 没有直接支持，需要自定义逻辑：先释放 shared，再获取 unique。\n",
    "- **`shared_lock` RAII**：`std::shared_lock<std::shared_mutex>` 自动管理 shared 锁。\n",
    "- **避免死锁**：同样遵循锁顺序规则；读锁不可升级为写锁（需手动转换）。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "vscode": {
     "languageId": "cpp"
    }
   },
   "outputs": [],
   "source": [
    "#include <shared_mutex>\n",
    "#include <thread>\n",
    "#include <vector>\n",
    "#include <iostream>\n",
    "\n",
    "std::shared_mutex sm;\n",
    "int data = 0;\n",
    "\n",
    "void reader() {\n",
    "    std::shared_lock lock(sm);\n",
    "    std::cout << \"read: \" << data << '\\n';\n",
    "}\n",
    "\n",
    "void writer() {\n",
    "    std::unique_lock lock(sm);\n",
    "    ++data;\n",
    "}\n",
    "\n",
    "int main() {\n",
    "    std::vector<std::thread> threads;\n",
    "    threads.emplace_back(writer);\n",
    "    threads.emplace_back(reader);\n",
    "    threads.emplace_back(reader);\n",
    "\n",
    "    for (auto& t : threads) t.join();\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 条件变量 `std::condition_variable`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "vscode": {
     "languageId": "cpp"
    }
   },
   "outputs": [],
   "source": [
    "std::mutex m;\n",
    "std::condition_variable cv;\n",
    "bool ready = false;\n",
    "\n",
    "void worker() {\n",
    "    std::unique_lock<std::mutex> lock(m);\n",
    "    cv.wait(lock, []{ return ready; }); // 使用 while/谓词\n",
    "    // 条件满足，执行任务\n",
    "}\n",
    "\n",
    "void notifier() {\n",
    "    {\n",
    "        std::lock_guard<std::mutex> lock(m);\n",
    "        ready = true;\n",
    "    }\n",
    "    cv.notify_one();\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- 使用 `while`/谓词而非 `if` 是为了避免虚假唤醒（spurious wakeup）或条件被其他线程改动。\n",
    "- `wait(lock, predicate)` 会在唤醒后重新检查条件，若为 false 则继续等待。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# `std::call_once` 与 `std::once_flag`\n",
    "\n",
    "- 确保某段初始化代码仅在多线程环境中执行一次，避免竞态。\n",
    "- `std::once_flag` 保存执行状态，`std::call_once(flag, callable, args...)` 在首次调用时执行，其他线程阻塞并跳过。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "vscode": {
     "languageId": "cpp"
    }
   },
   "outputs": [],
   "source": [
    "#include <iostream>\n",
    "#include <thread>\n",
    "#include <mutex>\n",
    "\n",
    "std::once_flag init_flag;\n",
    "\n",
    "void init_resource() {\n",
    "    std::call_once(init_flag, [] {\n",
    "        std::cout << \"initialize once\\n\";\n",
    "    });\n",
    "}\n",
    "\n",
    "int main() {\n",
    "    std::thread t1(init_resource);\n",
    "    std::thread t2(init_resource);\n",
    "    t1.join(); t2.join();\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# `std::future` / `std::promise` 协作模型\n",
    "\n",
    "`std::future` 可看作“结果的占位符”，而 `std::promise` 是“结果的生产者”。它们通过共享状态连接：\n",
    "\n",
    "- `std::promise<T>` 提供 `set_value`、`set_exception` 等接口来设定共享状态。\n",
    "- 调用 `promise.get_future()` 得到对应 `std::future<T>`，消费者可以 `get()` 或 `wait()` 取得结果。\n",
    "- 典型用途：在线程间传递结果或错误；比条件变量更直观，且支持异常传播。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "vscode": {
     "languageId": "cpp"
    }
   },
   "outputs": [],
   "source": [
    "#include <future>\n",
    "#include <iostream>\n",
    "#include <thread>\n",
    "\n",
    "void producer(std::promise<int> prom) {\n",
    "    try {\n",
    "        prom.set_value(42);   // 或 prom.set_exception(...)\n",
    "    } catch (...) {\n",
    "        prom.set_exception(std::current_exception());\n",
    "    }\n",
    "}\n",
    "\n",
    "int main() {\n",
    "    std::promise<int> prom;\n",
    "    std::future<int> fut = prom.get_future();\n",
    "    std::thread t(producer, std::move(prom));\n",
    "\n",
    "    std::cout << \"result = \" << fut.get() << '\\n'; // get() 会阻塞直到 set_value\n",
    "    t.join();\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    " `std::future` + `std::async`\n",
    "\n",
    "- `std::async` 返回 future，无需显式 promise。\n",
    "- 可用 `.wait_for()` / `.wait_until()` 检测状态；`get()` 只能调用一次。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# `std::promise` / `std::packaged_task` / `std::future`\n",
    "\n",
    "- `std::packaged_task`：将可调用对象包装成任务，持有 `promise`，可放入线程池或任务队列。\n",
    "- `std::future` 还可与 `std::shared_future` 配合，使多个消费者共享结果（`std::future` 无法多次 `get`）。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "vscode": {
     "languageId": "cpp"
    }
   },
   "outputs": [],
   "source": [
    "#include <future>\n",
    "#include <iostream>\n",
    "\n",
    "int work(int x) { return x * 2; }\n",
    "\n",
    "int main() {\n",
    "    std::packaged_task<int(int)> task(work);\n",
    "    std::future<int> fut = task.get_future();\n",
    "\n",
    "    std::thread t(std::move(task), 21);\n",
    "    std::cout << \"result = \" << fut.get() << '\\n';\n",
    "\n",
    "    t.join();\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 一次性获取多个锁\n",
    "\n",
    "- 使用 `std::lock` 同时加锁多个互斥量，它能避免死锁并保证所有锁都成功获取或全部释放。\n",
    "- 搭配 `std::scoped_lock`（C++17）或 `std::lock_guard` 手动构造。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "vscode": {
     "languageId": "cpp"
    }
   },
   "outputs": [],
   "source": [
    "#include <mutex>\n",
    "\n",
    "std::mutex m1, m2;\n",
    "\n",
    "void safe() {\n",
    "    std::scoped_lock lock(m1, m2); // 一次性获取多个锁\n",
    "    // 临界区\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 原子操作内存序语义\n",
    "\n",
    "- **`std::memory_order_seq_cst`**（顺序一致）：最严格，确保所有线程看到的操作顺序一致。\n",
    "- **`memory_order_acquire`**：用于读取操作，保证随后操作不会被重排到该读取之前（同步前序写入）。\n",
    "- **`memory_order_release`**：用于写入操作，保证之前操作不会被重排到该写入之后（同步后续读取）。\n",
    "- **`memory_order_relaxed`**: 仅保证读/写原子性，无顺序保证。用于计数器、统计信息，但需确保逻辑不依赖顺序。使用需谨慎，防止可见性错误。\n",
    "- 常见模式：写线程 `store(..., release)`，读线程 `load(..., acquire)`，形成 “happens-before” 关系。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "vscode": {
     "languageId": "cpp"
    }
   },
   "outputs": [],
   "source": [
    "#include <atomic>\n",
    "#include <thread>\n",
    "#include <cassert>\n",
    "\n",
    "std::atomic<int> data{0};\n",
    "std::atomic<bool> ready{false};\n",
    "\n",
    "void producer() {\n",
    "    data.store(42, std::memory_order_relaxed);\n",
    "    ready.store(true, std::memory_order_release);\n",
    "}\n",
    "\n",
    "void consumer() {\n",
    "    while (!ready.load(std::memory_order_acquire)) {}\n",
    "    assert(data.load(std::memory_order_relaxed) == 42);\n",
    "}\n",
    "\n",
    "int main() {\n",
    "    std::thread t1(producer), t2(consumer);\n",
    "    t1.join(); t2.join();\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# ABA 问题\n",
    "\n",
    "- 在 lock-free 结构中，指针从 A → B → A，看似未变但实际状态已被修改。\n",
    "- 解决：版本戳（带计数器的指针）、`std::atomic<std::shared_ptr>`、Hazard Pointers。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Double-checked locking\n",
    "\n",
    "- 在 C++11+ memory model、使用 `std::atomic<T*>` + `std::memory_order_acquire/release` + `std::mutex`，才能安全。\n",
    "- 典型模式：内层加锁保护初始化，外层原子检查避免重复加锁。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# `thread_local` 初始化/销毁\n",
    "\n",
    "- 每线程第一次访问时初始化。\n",
    "- 对象在线程退出时销毁；动态库中 thread_local 的生命周期与库加载/卸载有关（卸载时销毁）"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# `std::atomic<std::shared_ptr<T>>`\n",
    "\n",
    "- C++20 起提供偏特化；在 C++17 需使用 `std::atomic_store` / `std::atomic_load` 自由函数，因为 `shared_ptr` 不是平凡类型。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "vscode": {
     "languageId": "cpp"
    }
   },
   "outputs": [],
   "source": [
    "std::shared_ptr<Foo> p;\n",
    "std::atomic_store_explicit(&p, new_ptr, std::memory_order_release);\n",
    "auto q = std::atomic_load_explicit(&p, std::memory_order_acquire);"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 线程安全 Singleton\n",
    "\n",
    "C++11 起局部静态初始化线程安全："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "vscode": {
     "languageId": "cpp"
    }
   },
   "outputs": [],
   "source": [
    "Singleton& instance() {\n",
    "    static Singleton inst;\n",
    "    return inst;\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "若需懒加载 + 控制析构，可用 `std::call_once` 或 `atexit` 取消销毁。"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "C++17",
   "language": "C++17",
   "name": "xcpp17"
  },
  "language_info": {
   "codemirror_mode": "text/x-c++src",
   "file_extension": ".cpp",
   "mimetype": "text/x-c++src",
   "name": "c++",
   "version": "17"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
